import { Component, ElementRef, OnInit, ViewChild, Injector, OnDestroy } from '@angular/core';
import { Terminal, ITheme } from "xterm";
import { FitAddon } from 'xterm-addon-fit';
import { WebLinksAddon } from 'xterm-addon-web-links';
import { interval } from 'rxjs';
import { NotifyService } from '../../../service/notify.service';
import { SessionService } from '../../../service/session.service';
import { BaseTabComponent } from '../base-tab/base-tab.component';
import { ElectronService } from '../../../service/electron.service';
import { Setting, SettingService } from '../../../service/config.service';
import { MyTabPanel } from '../../public/tabview/tabview.component';

@Component({
  selector: 'app-base-term-tab',
  templateUrl: './base-term-tab.component.html',
  styleUrls: ['./base-term-tab.component.css']
})
export class BaseTermTabComponent extends BaseTabComponent implements OnInit, OnDestroy {

  private settingService: SettingService;
  protected electron: ElectronService;
  setting: Setting;

  xterm: Terminal;
  xtermCore: any;
  recvNewData = false;

  constructor(tabPanel: MyTabPanel, protected injector: Injector) {
    super(tabPanel, injector.get(SessionService), injector.get(NotifyService));
    this.settingService = injector.get(SettingService);
    this.electron = injector.get(ElectronService);
    this.setting = this.settingService.getConfig();
    let timer = interval(100);
    timer.subscribe(t => {
      if (this.recvNewData) {
        this.onStateChange.emit('DATA');
        this.recvNewData = false;
      }
    })
  }

  @ViewChild('terminal', { static: true }) terminalDiv: ElementRef;

  ngOnInit(): void {
  }
  ngAfterViewInit(): void {
    const theme: ITheme = {
      foreground: this.setting.terminal.foreground,//'#08cc6f',
      background: this.setting.terminal.background,//'#000000',
      selection: '#0a714e',
    }
    //this.terminalDiv.nativeElement.addEventListener('mousewheel', this.wheelHandler);

    this.xterm = new Terminal();
    this.xterm.loadAddon(new FitAddon());
    this.xterm.loadAddon(new WebLinksAddon((event, uri) => {
      if (this.electron.isElectron) this.electron.shell.openExternal(uri);
    }, {}, true))
    this.xterm.open(this.terminalDiv.nativeElement);
    this.xterm.setOption('theme', theme);
    //"'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace"
    this.xterm.setOption('fontFamily', this.setting.terminal.fontFamily);
    this.xterm.setOption('fontWeight', this.setting.terminal.fontBold ? 'bold' : 'normal');
    this.xterm.setOption('fontSize', this.setting.terminal.fontSize);
    this.xtermCore = (this.xterm as any)._core;

    setTimeout(() => this.xterm.focus());
  }
  onTabActive() {
    setTimeout(() => {
      this.resizeHandler();
      this.xterm.focus();
    })
  }
  onWindowResize() {
    this.resizeHandler();
  }
  /*
  wheelHandler = (event) => {
    let wheelDeltaY = 0
    if ('wheelDeltaY' in event) {
      wheelDeltaY = event['wheelDeltaY']
    } else {
      wheelDeltaY = event['deltaY']
    }

    var delta = 0
    if (event.altKey) {
      delta = Math.round(wheelDeltaY / 50)
    } else {
      delta = wheelDeltaY > 0 ? 1 : -1;
    }
    event.preventDefault();
    event.stopPropagation();
    this.session.write(Buffer.from((delta > 0 ? '\u001b0A' : '\u001b0B').repeat(Math.abs(delta)), 'utf-8'))
  }*/
  resizeHandler = () => {
    try {
      if (this.xterm.element && getComputedStyle(this.xterm.element).getPropertyValue('height') !== 'auto') {
        let t = window.getComputedStyle(this.xterm.element.parentElement!)
        let r = parseInt(t.getPropertyValue('height'))
        let n = Math.max(0, parseInt(t.getPropertyValue('width')))
        let o = window.getComputedStyle(this.xterm.element)
        let i = r - (parseInt(o.getPropertyValue('padding-top')) + parseInt(o.getPropertyValue('padding-bottom')))
        let l = n - (parseInt(o.getPropertyValue('padding-right')) + parseInt(o.getPropertyValue('padding-left'))) - this.xtermCore.viewport.scrollBarWidth
        let actualCellWidth = this.xtermCore._renderService.dimensions.actualCellWidth || 8
        let actualCellHeight = this.xtermCore._renderService.dimensions.actualCellHeight || 18
        let cols = Math.floor(l / actualCellWidth)
        let rows = Math.floor(i / actualCellHeight)

        if (!isNaN(cols) && !isNaN(rows)) {
          this.xterm.resize(cols, rows)
          if (this.session) this.session.resize(cols, rows);
        }
      }
    } catch (e) {
      // tends to throw when element wasn't shown yet
      console.warn('Could not resize xterm', e)
    }
  }
  ngOnDestroy(): void {
    if (this.session) this.session.kill();
    if (this.xterm) this.xterm.dispose();
  }
}
